package com.shop.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.shop.entity.*;
import com.shop.feign.ReductionController;
import com.shop.mapper.OrderDetailsMapper;
import com.shop.mapper.OrderMapper;
import com.shop.model.vo.OrderConfirmVo;
import com.shop.model.vo.OrderCount;
import com.shop.model.vo.Rsp;
import com.shop.feign.MessageFeign;
import com.shop.utils.Utils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * (Order)表服务接口
 *
 * @author makejava
 * @since 2020-11-21 12:10:57
 */
@Service
@AllArgsConstructor
public class OrderService {
    private final OrderMapper orderMapper;
    private final OrderDetailsMapper orderDetailsMapper;
    private final ReductionController reductionController;
    private final MessageFeign messageFeign;
    private final RedisService redisService;


    /**
     * @param order  订单数据
     * @param userId 用户id
     * @return com.shop.model.vo.Rsp
     * @author Clh
     * @description 下订单
     * @date 2020/11/24 10:48
     **/
    @Transactional
    public Rsp placeOrder(Order order, Integer userId) {
        System.out.println(order.getKey());
        //判断是否重复提交
        Object o = redisService.get(order.getKey());
        if (o == null) {
            return Rsp.fail().msg("不要重复提交订单");
        }
        //获取购物车数据
        List<MerchantBasket> list = orderMapper.selectBasket(order.getMerchantId(), userId);
        // Map<Integer, Integer> goodsIds = new HashMap<>();
        // //拿到购物车数据中的商品id和数量,判断是否充足
        // list.forEach(e -> goodsIds.put(e.getGoodsId(), e.getGoodsNum()));
        //判断库存是否充足,并且操作redis中的对应商品数量的加减
        // if (!getGoodsNumByRedis(goodsIds)) {
        //     return Rsp.fail().msg("商品数量不足请联系商家补货,重新下单");
        // }
        //开始下订单
        order.setNo(Utils.UUIDUtils());
        order.setUserId(userId);
        order.setCreateId(userId);
        double total = 0;
        int num = 0;
        List<OrderDetails> orderDetails = new ArrayList<>();
        for (MerchantBasket merchantBasket : list) {
            OrderDetails orderDetail = new OrderDetails();
            double sub = merchantBasket.getGoodsNum() * merchantBasket.getUnitPrice();
            total += sub;
            orderDetail.setGoodsIcon(merchantBasket.getGoodsPic());
            orderDetail.setGoodsId(merchantBasket.getGoodsId());
            orderDetail.setGoodsName(merchantBasket.getGoodsName());
            orderDetail.setGoodsOrderNum(merchantBasket.getGoodsNum());
            num += merchantBasket.getGoodsNum();
            orderDetail.setGoodsOrderPrice(merchantBasket.getUnitPrice());
            orderDetails.add(orderDetail);
        }
        total += order.getPostage();
        order.setNum(num);
        order.setTotalPrice(total);
        order.setActualPrice(total - order.getDiscount());
        orderMapper.add(order);
        orderDetails.forEach(e -> e.setOrderId(order.getId()));
        //批量插入
        orderDetailsMapper.insertList(orderDetails);
        //删除购物车
        orderMapper.deleteCartByUserAndMerchant(userId, order.getMerchantId());
        //发送消息给商家
        try {
            messageFeign.merchantSend(new Message("用户下订单请及时处理", order.getMerchantId() + ""));
            //将订单编号发送到延时队列
            messageFeign.orderMessage(new Message(order.getId()+"", order.getMerchantId() + ""));
        } catch (Exception e) {
            e.printStackTrace();
        }
        //删除key
        redisService.remove(order.getKey());
        return Rsp.success(true).msg("生成订单成功");
    }

    /**
     * 判断redis中
     *
     * @param goodsIds 要购买的商品数量和商品id
     * @return 返回是否可以购买
     */
    private boolean getGoodsNumByRedis(Map<Integer, Integer> goodsIds) {
        Set<Map.Entry<Integer, Integer>> entrySet = goodsIds.entrySet();
        for (Map.Entry<Integer, Integer> entry : entrySet) {
            Integer currentNum = (Integer) redisService.get("goods:" + entry.getKey());
            //如果redis中没有就查询数据库放到redis中
            if (currentNum == null) {
                Integer num = orderMapper.getNumByGoodsId(entry.getKey());
                redisService.set("goods:" + entry.getKey(), num);
                //再次判断数量是否充足
                if (num == 0 || num < entry.getValue()) {
                    return false;
                }
                //判断数量是否充足
            } else if (currentNum == 0 || currentNum < entry.getValue()) {
                return false;
            }
        }
        //能执行到这里说明库存是ok的,尝试去下单
        return tryOrder(goodsIds);
    }

    private boolean tryOrder(Map<Integer, Integer> goodsIds) {
        //这里执行设置redis中库存值的方法,设置完成后看是不是和自己期望的值一样
        //如果不一样就自旋继续尝试设置,直到库存不足或者自旋次数过多的时候,返回失败
        return true;
    }


    public Rsp getOrderList(Integer userId, String status) {
        return Rsp.success(orderMapper.selectByStatus(userId, status));
    }

    public Rsp getOrderById(Integer orderId) {
        return Rsp.success(orderMapper.getOrderById(orderId));
    }

    public Rsp orderCount(Integer userId) {
        List<Order> list = orderMapper.orderCount(userId);
        int unPay = 0;
        int consignment = 0;
        int payed = 0;
        for (Order order : list) {
            switch (order.getStatus()) {
                case "0":
                    unPay++;
                    break;
                case "1":
                    payed++;
                    break;
                case "2":
                    consignment++;
                    break;
                default:
            }
        }
        return Rsp.success(new OrderCount(unPay, payed, consignment));
    }

    /**
     * 获取当前用户,当前商家的购物车数据
     *
     * @param merchantId 商家
     * @return 数据
     */
    public Rsp getItemByMerchantId(Double distance, Integer merchantId, Integer userId) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        //获取购物车数据
        List<MerchantBasket> list = orderMapper.selectBasket(merchantId, userId);
        double total = 0;
        //获取商家所有的满减优惠金额
        Rsp rsp = reductionController.getReductionByMerchantId(merchantId);
        //将数据反序列化成优惠信息
        String result = mapper.writeValueAsString(rsp.getContent());
        List<Reduction> reductions = mapper.readValue(result, new TypeReference<List<Reduction>>() {
        });
        double discount = 0;
        int totalCount = 0;
        //计算需要支付的总价
        for (MerchantBasket merchantBasket : list) {
            double sub = merchantBasket.getGoodsNum() * merchantBasket.getUnitPrice();
            totalCount += merchantBasket.getGoodsNum();
            total += sub;
        }
        double postage = 2 * distance;
        total += postage;
        //将满减信息存入treeMap,排序得到最佳满减价格
        TreeMap<Double, Double> lists = new TreeMap<>();
        reductions.forEach(e -> lists.put(e.getReduce(), e.getFaceValue()));
        Set<Map.Entry<Double, Double>> entrySet = lists.entrySet();
        for (Map.Entry<Double, Double> entry : entrySet) {
            if (total > entry.getKey()) {
                discount = entry.getValue();
            } else {
                break;
            }
        }
        //生成一个唯一key防止用户重复提交,5分钟失效
        String key = UUID.randomUUID().toString();
        redisService.set(key, key, 5 * 60L);
        //生成订单信息
        OrderConfirmVo order = new OrderConfirmVo(list, total, discount, totalCount, key, postage);
        return Rsp.success(order);
    }

    public Rsp payOrder(Integer id, Integer userId) {
        orderMapper.payOrder(id);
        return Rsp.success(null);
    }
}
